package client;

import java.util.ArrayList;
import java.util.Collection;

import commands.*;

import view.*;
import controller.*;
import detector.Checkable;
import detector.CheckableButtonImpl;
import detector.CheckableWheel;
import detector.CheckableWheelImpl;
import detector.Checker;
import material.Clock;
import material.Material;
import model.*;

/**
 * Metronome est la classe "cliente" de l'application. C'est ici que tous les elements du metronome sont instancies 
 * et que l'injection des dependances est effectuee. 
 */
public class Metronome {
	
	public static void main(String[] args) {
		
		// Creation des differents composants de l'application
		// Partie PAC
		Engine engine = new EngineImpl(Constants.DEFAULT_TEMPO, Constants.DEFAULT_TIMESPERBAR);
		Controller controller = new ControllerImpl();
		IHM ihm = new IHMImpl();
		
		// Partie detection des evenements
		Collection<Checkable> checkables = new ArrayList<Checkable>();
		
		Checkable checkableButtonStart = new CheckableButtonImpl(0);
		Checkable checkableButtonStop = new CheckableButtonImpl(1);		
		Checkable checkableButtonInc = new CheckableButtonImpl(2);
		Checkable checkableButtonDec = new CheckableButtonImpl(3);
		
		CheckableWheel checkableWheel = new CheckableWheelImpl(Constants.DEFAULT_WHEEL_VALUE);
		
		checkables.add(checkableButtonStart);
		checkables.add(checkableButtonStop);
		checkables.add(checkableButtonInc);
		checkables.add(checkableButtonDec);
		checkables.add(checkableWheel);
		
		// Injections des dependances
		engine.setController(controller);
		controller.setEngine(engine);
		controller.setIHM(ihm);
		
		// Initialisations des commandes pour le moteur
		Command algorithmCommand = new HorlogeToEngineAlgorithmCommand(engine);
		
		engine.setRythmeAlgorithmCommand(algorithmCommand);
		
		// Initialisations des commandes pour le controleur
		Command[] buttonsCommands = new Command[4];
		buttonsCommands[0] = new ControllerToEngineStartCommand(engine);
		buttonsCommands[1] = new ControllerToEngineStopCommand(engine);
		buttonsCommands[2] = new ControllerToEngineIncTPBCommand(engine);
		buttonsCommands[3] = new ControllerToEngineDecTPBCommand(engine);	
		
		controller.setButtonsCommands(buttonsCommands);
		
		Command[] displayerCommands = new Command[2];
		displayerCommands[0] = new ControllerToIHMTurnOffLedCommand(Material.MaterialInstance().getDisplayer(), Constants.DEFAULT_TIME_LED);
		displayerCommands[1] = new ControllerToIHMTurnOffLedCommand(Material.MaterialInstance().getDisplayer(), Constants.DEFAULT_BAR_LED);

		controller.setDisplayerCommands(displayerCommands);

		// Initialisations des commandes pour la detection
		checkableButtonStart.setCommand(new DetectorToControllerButtonClickedCommand(controller, Constants.BUTTON_START_ID));
		checkableButtonStop.setCommand(new DetectorToControllerButtonClickedCommand(controller, Constants.BUTTON_STOP_ID));
		checkableButtonInc.setCommand(new DetectorToControllerButtonClickedCommand(controller, Constants.BUTTON_INC_ID));
		checkableButtonDec.setCommand(new DetectorToControllerButtonClickedCommand(controller, Constants.BUTTON_DEC_ID));
		
		checkableWheel.setCommand(new DetectorToControllerWheelChangedCommand(checkableWheel, controller));
		
		// Mise en place du mecanisme de detection des evenements
		Checker checker = new Checker();
		checker.setCheckables(checkables);
		
		Clock clock = Material.MaterialInstance().getClock();
		clock.activatePeriodically(checker, (float)10);
	}
	
}
